package com.gaff.emp.core.modules;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gaff.emp.core.modules.perm.dao.SysMenuDao;
import com.gaff.emp.core.modules.perm.dao.SysRoleDao;
import com.gaff.emp.core.modules.perm.dao.SysRoleMenuDao;
import com.gaff.emp.core.modules.perm.dao.SysUserDao;
import com.gaff.emp.core.modules.perm.entity.SysMenu;
import com.gaff.emp.core.modules.perm.entity.SysRole;
import com.gaff.emp.core.modules.perm.entity.SysRoleMenu;
import com.gaff.emp.core.modules.perm.entity.SysUser;
import com.gaff.emp.core.modules.sys.dao.SysDictDao;
import com.gaff.emp.core.modules.sys.entity.SysDict;
import com.gaff.emp.core.util.XmlUtil;
import org.dom4j.Element;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class InitDataBean implements InitializingBean {

    private static final String menuPath = "classpath*:/menu/*.xml";

    private static final String dictPath = "classpath*:/dict/*.xml";

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysMenuDao sysMenuDao;

    @Autowired
    private SysRoleDao sysRoleDao;

    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;

    @Autowired
    private SysDictDao sysDictDao;

    @Override
    public void afterPropertiesSet() throws Exception {
        initRootRoleAndAdminUser();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        for (Resource resource : resolver.getResources(menuPath)) {
            loadMenuFromResource(resource);
        }
        grantAllPerms();
        for (Resource resource : resolver.getResources(dictPath)) {
            loadDictFromResource(resource);
        }
    }

    private void loadDictFromResource(Resource resource) throws Exception {
        Element root = XmlUtil.getRootElementFromResource(resource);
        List<Element> dictEles = root.elements("dict");
        if (dictEles == null || dictEles.size() == 0) {
            return;
        }
        for (Element dictEle : dictEles) {
            String key = dictEle.attributeValue("key");
            String value = dictEle.attributeValue("value");
            if (StrUtil.isBlank(key) || StrUtil.isBlank(value)) {
                continue;
            }
            SysDict dict = sysDictDao.selectOne(Wrappers.<SysDict>query().eq("dict_key", key).eq("dict_value", value));
            if (dict != null) {
                continue;
            }
            dict = new SysDict();
            dict.setDictKey(key);
            dict.setDictValue(value);
            dict.setDescription(dictEle.attributeValue("desc"));
            dict.setNote(dictEle.attributeValue("note"));
            sysDictDao.insert(dict);
        }
    }

    private void initRootRoleAndAdminUser() {
        SysRole rootRole = sysRoleDao.selectOne(Wrappers.<SysRole>query().eq("role_code", "ROOT"));
        if (rootRole == null) {
            rootRole = new SysRole();
            rootRole.setRoleName("超级管理员");
            rootRole.setRoleCode("ROOT");
            rootRole.setRoleDesc("超级管理员");
            rootRole.setNote("系统超级管理员角色，不能被修改");
            sysRoleDao.insert(rootRole);
        }
        SysUser adminUser = sysUserDao.selectOne(Wrappers.<SysUser>query().eq("username", "admin"));
        if (adminUser == null) {
            adminUser = new SysUser();
            adminUser.setUsername("admin");
            adminUser.setPassword(SysUser.initPassword);
            adminUser.setRoleId(rootRole.getId());
            adminUser.setRoleName(rootRole.getRoleName());
            adminUser.setStatus(SysUser.normal);
            sysUserDao.insert(adminUser);
        }
    }

    private void grantAllPerms() {
        SysRole rootRole = sysRoleDao.selectOne(Wrappers.<SysRole>query().eq("role_code", "ROOT"));
        List<SysMenu> allMenus = sysMenuDao.selectList(Wrappers.emptyWrapper());
        List<SysRoleMenu> roleMenus = sysRoleMenuDao.selectList(Wrappers.<SysRoleMenu>query().eq("role_id", rootRole.getId()));
        for (SysMenu menu : allMenus) {
            boolean isExists = false;
            for (SysRoleMenu roleMenu : roleMenus) {
                if (roleMenu.getMenuId() == menu.getId()) {
                    isExists = true;
                    break;
                }
            }
            if (!isExists) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(rootRole.getId());
                roleMenu.setMenuId(menu.getId());
                sysRoleMenuDao.insert(roleMenu);
            }
        }
    }

    private void loadMenuFromResource(Resource resource) throws Exception {
        Element root = XmlUtil.getRootElementFromResource(resource);
        List<Element> catalogEles = root.elements("catalog");
        if (catalogEles == null || catalogEles.size() == 0) {
            return;
        }
        for (Element catalogEle : catalogEles) {
            String code = catalogEle.attributeValue("code");
            if (StrUtil.isBlank(code)) {
                continue;
            }
            SysMenu catalog = sysMenuDao.selectOne(Wrappers.<SysMenu>query().eq("code", code));
            if (catalog == null) {
                catalog = saveCatalogFromElement(catalogEle);
            }
            List<Element> menuEles = catalogEle.elements("menu");
            if (menuEles == null || menuEles.size() == 0) {
                continue;
            }
            for (Element menuEle : menuEles) {
                String menuCode = menuEle.attributeValue("code");
                if (StrUtil.isBlank(menuCode)) {
                    continue;
                }
                SysMenu menu = sysMenuDao.selectOne(Wrappers.<SysMenu>query().eq("code", menuCode));
                if (menu == null) {
                    saveMenuFromElement(catalog, menuEle);
                }
            }
        }
    }

    private void saveMenuFromElement(SysMenu catalog, Element ele) {
        SysMenu menu = new SysMenu();
        menu.setType(SysMenu.menu);
        menu.setParentId(catalog.getId());
        mergeProperty(menu, ele);
        sysMenuDao.insert(menu);
    }

    private SysMenu saveCatalogFromElement(Element ele) {
        SysMenu catalog = new SysMenu();
        catalog.setType(SysMenu.catalog);
        catalog.setParentId(0);
        mergeProperty(catalog, ele);
        sysMenuDao.insert(catalog);
        return catalog;
    }

    private void mergeProperty(SysMenu menu, Element ele) {
        menu.setCode(ele.attributeValue("code"));
        menu.setName(ele.attributeValue("name"));
        menu.setIcon(ele.attributeValue("icon"));
        menu.setUrl(ele.attributeValue("url"));
        menu.setPerm(ele.attributeValue("perm"));
        String isHidden = ele.attributeValue("isHidden");
        if (StrUtil.isNotBlank(isHidden) && Boolean.valueOf(isHidden)) {
            menu.setIsHidden(SysMenu.hidden);
        } else {
            menu.setIsHidden(SysMenu.show);
        }
        String sort = ele.attributeValue("sort");
        if (StrUtil.isNotBlank(sort)) {
            menu.setSort(Integer.valueOf(sort));
        }
    }


}
